home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / os2 / pmnos11s / lpdsubr.c < prev    next >
C/C++ Source or Header  |  1993-07-30  |  36KB  |  1,534 lines

  1. /* Internet LPD Server subroutines
  2.  *   written by David Johnson (dave@cs.olemiss.edu)
  3.  *
  4.  * This code is in the public domain.
  5.  *
  6.  * Revision History:
  7.  *
  8.  * Revision 1.4  91/09/27  dave (from Hans-Juergen)
  9.  * Changed definitions of default files to handle changing NOS logical
  10.  *     root directory
  11.  * Actually retrieve the page cost (co) from printcap for pac
  12.  *
  13.  * Revision 1.3  91/09/19  dave
  14.  * Read the ty capability even when interface is not an internal device
  15.  *
  16.  * Revision 1.2  91/09/17  dave
  17.  * Moved output processing flags to device structure so all device types
  18.  *    can use them
  19.  *
  20.  * Revision 1.1  91/09/14  dave (from marko winblad)
  21.  * Perform an ioctl on DOS device to make sure it is opened in "binary" mode
  22.  *
  23.  * Revision 1.0  91/09/04  dave
  24.  * Initial Release
  25.  *
  26.  */
  27. #include <stdio.h>
  28. #include <fcntl.h>
  29. #include <ctype.h>
  30. #include <time.h>
  31. #include <sys/stat.h>
  32. #ifdef    __TURBOC__
  33. #include <io.h>
  34. #include <dir.h>
  35. #endif
  36. #include "global.h"
  37. #include "mbuf.h"
  38. #include "proc.h"
  39. #include "iface.h"
  40. #include "asy.h"
  41. #include "i8250.h"
  42. #include "devparam.h"
  43. #include "socket.h"
  44. #include "dirutil.h"
  45. #include "commands.h"
  46. #include "files.h"
  47. #include "lp.h"
  48. #include "lpd.h"
  49. #include "lpdfilt.h"
  50.  
  51. /* in files.c */
  52. extern char *roordircat __ARGS((char *directory));
  53.  
  54. /* in lpd.c */
  55. extern int  is_lpd_active __ARGS((void));
  56.  
  57. /* local functions - public */
  58.        int  get_acct_info __ARGS((char *queue, char **af, int *pc));
  59.        int  get_job_list __ARGS((char *directory, struct job_entry **job_list));
  60.        char **get_queue_list __ARGS((void));
  61.        char *get_spool_dir __ARGS((char *queue));
  62.        struct LPDstatus *get_status_entry __ARGS((char *queue));
  63.        int  is_unspooler_active __ARGS((char *queue, char **job));
  64.        int  kill_unspooler __ARGS((char *queue));
  65.        void lpd_log __ARGS((struct LPDtrans *LPD, char *message, ...));
  66.        char *read_printcap __ARGS((struct LPDtrans *LPD, char *queue));
  67.        int  read_status __ARGS((char *queue, unsigned int *flags, unsigned int *next_seq, char **message));
  68.        void set_status_message __ARGS((char **dest, char *message, ...));
  69.        char *time_string __ARGS((void));
  70.  
  71. /* local functions - exported to lpd.c */
  72.        void free_queue_status __ARGS((void));
  73.        int  get_new_sequence_no __ARGS((struct LPDtrans *LPD));
  74.        int  init_queue_status __ARGS((void));
  75.  
  76. /* local functions - exported to lpdunsp.c */
  77.        int  cf_parse __ARGS((struct LPDtrans *LPD, FILE *cfp));
  78.        int  close_device __ARGS((struct LPDtrans *LPD));
  79.        void free_job __ARGS((struct LPDjob *job));
  80.        struct LPDdevice *get_device_entry __ARGS((char *device_name));
  81.        int  open_device __ARGS((struct LPDtrans *LPD));
  82.        int  save_status __ARGS((char *queue, unsigned int flags, unsigned int next_seq));
  83.  
  84. /* local functions - exported to lpc.c */
  85.        int  clear_status_flag __ARGS((char *queue, int flag));
  86.        int  get_job_count __ARGS((char *queue));
  87.        int  set_status_flag __ARGS((char *queue, int flag));
  88.        int  signal_queue __ARGS((char *queue));
  89.  
  90. /* local functions - private */
  91. static int  job_compare __ARGS((char *entry1, char *entry2));
  92. static char *pc_get_entry __ARGS((char *bp, char *name));
  93. static int  pc_get_number __ARGS((char *bp, char *id));
  94. static int  pc_get_flag __ARGS((char *bp, char *id));
  95. static char *pc_get_string __ARGS((char *bp, char *id, char **area));
  96. static unsigned int get_queue_count __ARGS((void));
  97. static char *get_primary_queue_name __ARGS((char *queue));
  98. static void read_lock_file __ARGS((char *directory, unsigned int *flags, unsigned int *next_seq));
  99. static void set_device_params __ARGS((struct LPDtrans *LPD, char *params));
  100. static void write_lock_file __ARGS((char *directory, unsigned int flags, unsigned int next_seq));
  101. static int  load_status __ARGS((char *queue, unsigned int *flags, unsigned int *next_seq));
  102. static void write_lock_file __ARGS((char *directory, unsigned int flags, unsigned int next_seq));
  103. static void read_lock_file __ARGS((char *directory, unsigned int *flags, unsigned int *next_seq));
  104. static void i_lpd_log __ARGS((struct LPDtrans *LPD, char *message, va_list args));
  105. static void i_set_status_message __ARGS((char **dest, char *message, va_list args));
  106.  
  107. /* Status messages */
  108. static char checking[] = "Checking queue at %s";
  109. static char done[] = "Work done at %s";
  110. static char processing[] = "Processing, active job started %s";
  111. static char busy_device[] = "Waiting for %s to become free since %s";
  112. static char offline_device[] = "Waiting for %s to become ready since %s (offline?)";
  113. static char device_opened[] = "Printer %s output %s opened at %s";
  114.  
  115.  
  116. static struct LPDstatus *queue_list;
  117.  
  118. /*
  119.  * All devices which are supported
  120.  */
  121. static struct LPDdevice device_list[] = {
  122.     {"LPT1", 0},
  123.     {"LPT2", 0},
  124.     {"LPT3", 0},
  125.     {"COM1", 0},
  126.     {"COM2", 0},
  127.     {"COM3", 0},
  128.     {"COM4", 0},
  129.     {"sl1" , 0},        /* internal NOS serial interfaces */
  130.     {"sl2" , 0},
  131.     {"sl3" , 0},
  132.     {"sl4" , 0},
  133.     { NULL , 0}};
  134.  
  135.  
  136. /*
  137.  * Scan spool directory and return the list of jobs found in job order
  138.  */
  139. int
  140. get_job_list( directory, job_list )
  141. char *directory;
  142. struct job_entry **job_list;
  143. {
  144.     char *strdup(), *path, *cf_path;
  145.     struct ffblk file_info;
  146.     struct stat statbuf;
  147.     struct job_entry *tmp_job_list;
  148.     unsigned int job_count, job_list_size;
  149.  
  150.     path = pathname( directory, "cf*.*" );
  151.     job_count = 0;
  152.     tmp_job_list = callocw( 20, sizeof( struct job_entry ) );
  153.     job_list_size = 20;
  154.     if( findfirst( path, &file_info, 0 ) == 0 ) {
  155.         tmp_job_list[job_count].j_name = strdup( file_info.ff_name );
  156.         tmp_job_list[job_count].j_priority = file_info.ff_name[2];
  157.         cf_path = pathname( directory, file_info.ff_name );
  158.         stat( cf_path, &statbuf );
  159.         free( cf_path );
  160.         tmp_job_list[job_count].j_time = statbuf.st_mtime;
  161.         job_count++;
  162.         YIELD;
  163.         while( findnext( &file_info ) == 0 ) {
  164.             tmp_job_list[job_count].j_name = strdup( file_info.ff_name );
  165.             tmp_job_list[job_count].j_priority = file_info.ff_name[2];
  166.             cf_path = pathname( directory, file_info.ff_name );
  167.             stat( cf_path, &statbuf );
  168.             free( cf_path );
  169.             tmp_job_list[job_count].j_time = statbuf.st_mtime;
  170.             if( ++job_count > job_list_size ) {
  171.                 job_list_size += 20;
  172.                 tmp_job_list = realloc( tmp_job_list,
  173.                         job_list_size*sizeof(struct job_entry) );
  174.             }
  175.             YIELD;
  176.         }
  177.         YIELD;
  178.         qsort( (char *)tmp_job_list, job_count, sizeof( struct job_entry ), job_compare );
  179.     }
  180.     free( path );
  181.  
  182.     if( job_count == 0 ) {
  183.         free( tmp_job_list );
  184.         *job_list = NULL;
  185.     } else {
  186.         *job_list = tmp_job_list;
  187.     }
  188.     YIELD;
  189.     return job_count;
  190. }
  191.  
  192. /*
  193.  * Compare two job entries for qsort
  194.  */
  195. static int
  196. job_compare( entry1, entry2 )
  197. char *entry1, *entry2;
  198. {
  199.     struct job_entry *p1, *p2;
  200.  
  201.     p1 = (struct job_entry *)entry1;
  202.     p2 = (struct job_entry *)entry2;
  203.     if( (p1)->j_priority < (p2)->j_priority )
  204.         return -1;
  205.     if( (p1)->j_priority > (p2)->j_priority )
  206.         return 1;
  207.     if( (p1)->j_time < (p2)->j_time )
  208.         return -1;
  209.     if( (p1)->j_time > (p2)->j_time )
  210.         return 1;
  211.     return 0;
  212. }
  213.  
  214. /*
  215.  * Convert string to upper case
  216.  */
  217. static void
  218. uppercase_string( string )
  219. char *string;
  220. {
  221.     char *cp = string;
  222.  
  223.     while( *cp ) {
  224.         if( islower( *cp ) )
  225.             *cp = toupper( *cp );
  226.         cp++;
  227.     }
  228. }
  229.  
  230. /*
  231.  * Read the printcap entries use in printing and spooling.
  232.  * Return the primary queue name.
  233.  */
  234. char *
  235. read_printcap( LPD, queue )
  236. struct LPDtrans *LPD;
  237. char *queue;
  238. {
  239.     struct iface *ifp;
  240.     char *bp, *pcptr, *path;
  241.     char *primary_name;
  242.     FILE *fp;
  243.  
  244.     LPD->pc = (struct LPDpr *)mallocw( sizeof(struct LPDpr) );
  245.     bp = LPD->pc->buffer;
  246.  
  247.     if( (primary_name = pc_get_entry( bp, queue )) == NULL ) {
  248.         tprintf( "queue %s not found.\n", queue );
  249.         return NULL;
  250.     }
  251.     LPD->name = primary_name;
  252.  
  253.     pcptr = LPD->pc->strings;
  254.  
  255.     if( (LPD->pc->SD = pc_get_string( bp, "sd", &pcptr )) == NULL )
  256.             LPD->pc->SD = Lpdsd;
  257.     if( *LPD->pc->SD != '/' )
  258.         LPD->pc->SD = rootdircat( LPD->pc->SD );
  259.  
  260.     /*
  261.      * Check that spool directory exists
  262.      */
  263.     path = pathname( LPD->pc->SD, "testfile" );
  264.     fp = fopen( path, "w" );
  265.     if( fp == NULL ) {
  266.         tprintf( "lpd: spool directory (%s) may not exist\n", LPD->pc->SD );
  267.         free( path );
  268.         return NULL;
  269.     }
  270.     fclose( fp );
  271.     remove( path );
  272.     free( path );
  273.     YIELD;
  274.  
  275.     if( (LPD->pc->LP = pc_get_string( bp, "lp", &pcptr )) == NULL )
  276.             LPD->pc->LP = D_DEVLP;
  277.  
  278.     if( (ifp = if_lookup( LPD->pc->LP )) != NULL ) {
  279.         /* INTERNAL DEVICE; MUST BE SERIAL PORT */
  280.  
  281.         if( (LPD->pc->BR = pc_get_number( bp, "br" )) < 0 )
  282.             LPD->pc->BR = D_BAUDRATE;
  283.         (*ifp->ioctl)( ifp, PARAM_SPEED, TRUE, LPD->pc->BR );
  284.     } else {
  285.         uppercase_string( LPD->pc->LP );
  286.     }
  287.     LPD->pc->TY = pc_get_string( bp, "ty", &pcptr );
  288.  
  289.     if( (LPD->pc->LF = pc_get_string( bp, "lf", &pcptr )) == NULL )
  290.         LPD->pc->LF = Lpdlogfile;
  291.     if( *LPD->pc->LF != '/' )
  292.         LPD->pc->LF = rootdircat( LPD->pc->LF );
  293.     if( (LPD->pc->FF = pc_get_string( bp, "ff", &pcptr )) == NULL )
  294.         LPD->pc->FF = D_FF;
  295.     if( (LPD->pc->PW = pc_get_number( bp, "pw" )) < 0 )
  296.         LPD->pc->PW = D_WIDTH;
  297.     if( (LPD->pc->PL = pc_get_number( bp, "pl" )) < 0 )
  298.         LPD->pc->PL = D_LENGTH;
  299.     if( (LPD->pc->PX = pc_get_number( bp, "px" )) < 0 )
  300.         LPD->pc->PX = D_PWIDTH;
  301.     if( (LPD->pc->PY = pc_get_number( bp, "py" )) < 0 )
  302.         LPD->pc->PY = D_PLENGTH;
  303.  
  304.     if( (LPD->pc->MC = pc_get_number( bp, "mc" )) < 0 )
  305.         LPD->pc->MC = D_MAXCOPIES;
  306.     if( (LPD->pc->MX = pc_get_number( bp, "mx" )) < 0 )
  307.         LPD->pc->MX = D_MAXJOBSIZE;
  308.  
  309.     if( (LPD->pc->IF = pc_get_string( bp, "if", &pcptr )) == NULL )
  310.         LPD->pc->IF = D_IF;
  311.  
  312.     if( (LPD->pc->OF = pc_get_string( bp, "of", &pcptr )) == NULL )
  313.         LPD->pc->OF = D_OF;
  314.  
  315.     if( (LPD->pc->FX = pc_get_string( bp, "fx", &pcptr )) == NULL )
  316.         LPD->pc->FX = D_FILTERS;
  317.  
  318.     YIELD;
  319.  
  320.     /* Other filter specifications - presently not used */
  321.     LPD->pc->CF = pc_get_string( bp, "cf", &pcptr );
  322.     LPD->pc->DF = pc_get_string( bp, "df", &pcptr );
  323.     LPD->pc->GF = pc_get_string( bp, "gf", &pcptr );
  324.     LPD->pc->NF = pc_get_string( bp, "nf", &pcptr );
  325.     LPD->pc->TF = pc_get_string( bp, "tf", &pcptr );
  326.     LPD->pc->VF = pc_get_string( bp, "vf", &pcptr );
  327.  
  328.     LPD->pc->CM = pc_get_string( bp, "cm", &pcptr );
  329.     LPD->pc->AF = pc_get_string( bp, "af", &pcptr );
  330.     if( *LPD->pc->AF != '/' )
  331.         LPD->pc->AF = rootdircat( LPD->pc->AF );
  332.     LPD->pc->LD = pc_get_string( bp, "ld", &pcptr );
  333.     LPD->pc->TR = pc_get_string( bp, "tr", &pcptr );
  334.     LPD->pc->JL = pc_get_string( bp, "jl", &pcptr );
  335.     LPD->pc->JT = pc_get_string( bp, "jt", &pcptr );
  336.     LPD->pc->FL = pc_get_string( bp, "fl", &pcptr );
  337.     LPD->pc->FT = pc_get_string( bp, "ft", &pcptr );
  338.  
  339.     YIELD;
  340.  
  341.     LPD->pc->AB = pc_get_flag( bp, "ab" );
  342.     LPD->pc->FO = pc_get_flag( bp, "fo" );
  343.     LPD->pc->FQ = pc_get_flag( bp, "fq" );
  344.     LPD->pc->HL = pc_get_flag( bp, "hl" );
  345.     LPD->pc->SB = pc_get_flag( bp, "sb" );
  346.     LPD->pc->SC = pc_get_flag( bp, "sc" );
  347.     LPD->pc->SF = pc_get_flag( bp, "sf" );
  348.     LPD->pc->SH = pc_get_flag( bp, "sh" );
  349.     LPD->pc->SS = pc_get_flag( bp, "ss" );
  350.  
  351.     /* PostScript capabilities */
  352.     LPD->pc->PS = pc_get_string( bp, "ps", &pcptr );
  353.     LPD->pc->PE = pc_get_string( bp, "pe", &pcptr );
  354.     LPD->pc->DP = pc_get_flag( bp, "dp" );
  355.  
  356.     YIELD;
  357.     return( primary_name );
  358. }
  359.  
  360. /*
  361.  * Set the device characteristics of an internal NOS interface
  362.  */
  363. static void
  364. set_device_params( LPD, params)
  365. struct LPDtrans *LPD;
  366. char *params;
  367. {
  368.     struct iface *ifp = NULL;
  369.     int negate;
  370.     char *tempparams, *option;
  371.  
  372.     if( LPD->status->type == INTERNAL )
  373.         ifp = LPD->status->device.ifp;
  374.  
  375.     tempparams = strdup( params );
  376.  
  377.     option = strtok( tempparams, " " );
  378.     while( option ) {
  379.         negate = 0;
  380.         if( *option == '-' ) {
  381.             negate = 1;
  382.             option++;
  383.         }
  384.         if( strncmp( option, "even", 4 ) == 0 && ifp ) {
  385.  
  386.             if( negate )                /* not even */
  387.                 (*ifp->ioctl)( ifp, PARAM_PARITY, TRUE, 0 );
  388.             else                    /* even */
  389.                 (*ifp->ioctl)( ifp, PARAM_PARITY, TRUE, 1 );
  390.  
  391.         } else if( strncmp( option, "odd", 3 ) == 0 && ifp ) {
  392.  
  393.             if( negate )                /* not odd */
  394.                 (*ifp->ioctl)( ifp, PARAM_PARITY, TRUE, 0 );
  395.             else                    /* odd */
  396.                 (*ifp->ioctl)( ifp, PARAM_PARITY, TRUE, 2 );
  397.  
  398.         } else if( strncmp( option, "rts", 3 ) == 0 && ifp ) {
  399.  
  400.             (*ifp->ioctl)( ifp, PARAM_RTS, TRUE, !negate );
  401.  
  402.         } else if( strncmp( option, "dtr", 3 ) == 0 && ifp ) {
  403.  
  404.             (*ifp->ioctl)( ifp, PARAM_DTR, TRUE, !negate );
  405.  
  406.         } else if( strncmp( option, "nl", 2 ) == 0 ) {
  407.  
  408.             if( negate )
  409.                 LPD->device->flags &= ~CRMOD;
  410.             else
  411.                 LPD->device->flags |= CRMOD;
  412.  
  413.         } else if( strncmp( option, "tabs", 4 ) == 0 ) {
  414.  
  415.             if( negate )
  416.                 LPD->device->flags |= XTABS;
  417.             else
  418.                 LPD->device->flags &= ~XTABS;
  419.  
  420.         }
  421.         option = strtok( NULL, " " );
  422.     }
  423.     free( tempparams );
  424. }
  425.  
  426. /*
  427.  * Open the specified device if it is not busy, else wait for it to free.
  428.  */
  429. int
  430. open_device( LPD )
  431. struct LPDtrans *LPD;
  432. {
  433.     struct LPDstatus *status = LPD->status;
  434.  
  435.     if( status->device_open == 0 ) {
  436.         set_status_message( &LPD->status->message, busy_device, LPD->pc->LP, time_string() );
  437.         while( LPD->device->busy )    /* another unspooler is using */
  438.             YIELD;
  439.  
  440.         if( (status->device.ifp = if_lookup( LPD->pc->LP )) == NULLIF ) {
  441.             /* MUST BE A DOS FILE DEVICE */
  442.  
  443.             status->type = EXTERNAL;
  444.             if( (status->device.fp = fopen( LPD->pc->LP, "ab" )) == NULL ) {
  445.                 tprintf( "device could not be opened\n" );
  446.                 return -1;
  447.             }
  448.             /*
  449.              * Make sure device is opened in "binary" mode
  450.              */
  451. #ifdef LPD_DEBUG
  452.             tprintf( "isatty(%d) returns %d\n",
  453.                 fileno( status->device.fp ),
  454.                 isatty( fileno( status->device.fp ) ));
  455.             tflush();
  456. #endif
  457.             if( isatty( status->device.fp->fd ) ) {
  458. #ifdef LPD_DEBUG        tprintf( "ioctl(%d,0) returns %04x\n",
  459.                     fileno( status->device.fp ),
  460.                     ioctl( fileno( status->device.fp ), 0);
  461.                 tflush();
  462. #endif
  463.                 ioctl( fileno( status->device.fp ), 1,
  464.                     0xff &
  465.                     (ioctl( fileno( status->device.fp ),0)
  466.                     | 0x20 ) );
  467.             }
  468. #ifdef LPD_DEBUG
  469.             tprintf( "ioctl(%d,0) returns %04x\n",
  470.                 fileno( status->device.fp ),
  471.                 ioctl( fileno( status->device.fp ), 0 ) );
  472.             tflush();
  473. #endif
  474.         } else {
  475.             if( (status->device.ifp)->dev >= ASY_MAX
  476.                 || Asy[(status->device.ifp)->dev].iface != status->device.ifp ){
  477.                 /* INVALID INTERNAL INTERFACE; MAKE EXTERNAL */
  478.  
  479.                 status->type = EXTERNAL;
  480.                     if( (status->device.fp = fopen( LPD->pc->LP, "ab" )) == NULL ) {
  481.                         tprintf( "device could not be opened\n" );
  482.                         return -1;
  483.                     }
  484.             } else {
  485.                 status->type = INTERNAL;
  486.             }
  487.         }
  488.         if( LPD->pc->TY )
  489.             set_device_params( LPD, LPD->pc->TY );
  490.         LPD->device->busy = 1;        /* mark device as busy */
  491.         LPD->status->device_open = 1;
  492.         LPD->status->jobno = 0;
  493.         set_status_message( &LPD->status->message, device_opened, LPD->name, LPD->pc->LP, time_string() );
  494.     }
  495.     return 0;
  496. }
  497.  
  498. /*
  499.  * Close the device file handle and free device
  500.  */
  501. int
  502. close_device( LPD )
  503. struct LPDtrans *LPD;
  504. {
  505.     if( LPD->status->device_open ) {
  506.         if( LPD->status->type == EXTERNAL ) {
  507.             fclose( LPD->status->device.fp );
  508.             LPD->status->device.fp = (FILE *)0;
  509.         }
  510.         LPD->status->device_open = 0;
  511.         LPD->device->busy = 0;
  512.     }
  513. }
  514.  
  515. /*
  516.  * Read the control file and extract necessary entries.
  517.  * Returns -1 if data file(s) is not found or size exceeds MX.
  518.  */
  519. int
  520. cf_parse( LPD, cfp )
  521. struct LPDtrans *LPD;
  522. FILE *cfp;
  523. {
  524.     char line[81], *ptr, *strdup();
  525.     char *path;
  526.     struct LPDjob *job;
  527.  
  528.     job = LPD->job;
  529.     while( fgets( line, 80, cfp ) != NULL ) {
  530.         rip( line );
  531.         switch( *line ) {
  532.             case 'N':
  533.             case 'U':
  534.                 /* ignore */
  535.                 break;
  536.             case 'C':
  537.                 job->class = strdup( line+1 );
  538.                 break;
  539.             case 'D':
  540.                 job->date = strdup( line+1 );
  541.                 break;
  542.             case 'H':
  543.                 job->hostname = strdup( line+1 );
  544.                 break;
  545.             case 'I':
  546.                 job->indent = atoi( line+1 );
  547.                 break;
  548.             case 'J':
  549.                 job->jobname = strdup( line+1 );
  550.                 break;
  551.             case 'L':
  552.                 job->username = strdup( line+1 );
  553.                 break;
  554.             case 'M':
  555.                 job->mail = strdup( line+1 );
  556.                 break;
  557.             case 'P':
  558.                 job->person = strdup( line+1 );
  559.                 break;
  560.             case 'S':
  561.                 job->noheader = strdup( line+1 );
  562.                 break;
  563.             case 'R':
  564.                 job->account = strdup( line+1 );
  565.                 break;
  566.             case 'W':
  567.                 job->width = atoi( line+1 );
  568.                 break;
  569.             case 'T':
  570.                 job->title = strdup( line+1 );
  571.                 break;
  572.             default:
  573.                 if( islower( *line ) ) {
  574.                     struct stat fstatus;
  575.  
  576.                     if( strchr( LPD->pc->FX, *line ) == NULL )
  577.                         return -1;
  578.                     path = pathname( LPD->pc->SD, line+1 );
  579.                     if( stat( path, &fstatus ) != 0 ) {
  580.                         free( path );
  581.                         lpd_log( LPD, "cf_parse: %s not found", line+1 );
  582.                         return -1;
  583.                     }
  584.                     free( path );
  585.                     job->size += (fstatus.st_size + 1023)/1024;
  586.                     if( LPD->pc->MX && job->size > LPD->pc->MX ) {
  587.                         lpd_log( LPD, "cf_parse: job %s exceeds max. job size", job->jobname );
  588.                         return -1;
  589.                     }
  590.                 }
  591.         }
  592.         YIELD;
  593.     }
  594.  
  595.     /*
  596.      * Handle missing items
  597.      */
  598.     if( LPD->job->width == 0 )
  599.         LPD->job->width = LPD->pc->PW;
  600.     if( LPD->job->class == NULL && LPD->job->hostname )
  601.         LPD->job->class = strdup( LPD->job->hostname );
  602.  
  603.     return 0;
  604. }
  605.  
  606. /*
  607.  * free the job fields allocated in cf_parse
  608.  */
  609. void
  610. free_job( job )
  611. struct LPDjob *job;
  612. {
  613.     if( job == NULL )
  614.         return;
  615.  
  616.     if( job->class )
  617.         free( job->class );
  618.     if( job->date )
  619.         free( job->date );
  620.     if( job->hostname )
  621.         free( job->hostname );
  622.     if( job->jobname )
  623.         free( job->jobname );
  624.     if( job->username )
  625.         free( job->username );
  626.     if( job->mail )
  627.         free( job->mail );
  628.     if( job->person )
  629.         free( job->person );
  630.     if( job->noheader )
  631.         free( job->noheader );
  632.     if( job->account )
  633.         free( job->account );
  634.     if( job->title )
  635.         free( job->title );
  636.     free( job );
  637.     job = NULL;
  638. }
  639.  
  640. /******************************************************************************
  641. **                                                                           **
  642. **  Printcap file handling routines                                          **
  643. **                                                                           **
  644. ******************************************************************************/
  645.  
  646. /*
  647. ** pc_get_entry - get the printcap entry for printer name, and put it
  648. **           in bp (which must be an array of 1024 chars).  Returns
  649. **           PRIMARY_NAME if printcap entry found, NULL if not found or
  650. **           printcap file not found.
  651. */
  652. static char *
  653. pc_get_entry( bp, name )
  654. char *bp, *name;
  655. {
  656.     FILE *fp;
  657.     char *cp, *pn, *primary_name;
  658.     short len = strlen( name );
  659.  
  660. #ifdef LPD_DEBUG
  661.     tprintf( "pc_get_entry( %s )\n", name );
  662.     tflush();
  663. #endif
  664.  
  665.     if( (fp = fopen( Lpdprintcap, "r" )) == (FILE *) NULL )
  666.         return( NULL );
  667.  
  668.     while( fgets( bp, 1024, fp ) != NULL ) {
  669.         /* skip comments */
  670.         if( *bp == '#' )
  671.             continue;
  672.         for( cp = bp; isspace( *cp ); cp++ )
  673.             ;
  674.         do {
  675.             if( strncmp( name, cp, len ) == 0 ) {
  676.                 while( *(cp = &bp[strlen(bp) - 2]) == '\\' )
  677.                     fgets( cp, 1024, fp );
  678.                 fclose( fp );
  679.                 len = 0;
  680.                 cp = bp;
  681.                 while( *cp && *cp != ':' && *cp != '|' ) {
  682.                     ++len;
  683.                     ++cp;
  684.                 }
  685.                 primary_name = (char *)mallocw(len+1);
  686.                 cp = bp;
  687.                 pn = primary_name;
  688.                 while( *cp && *cp != ':' && *cp != '|' )
  689.                     *pn++ = *cp++;
  690.                 *pn = NULL;
  691.                 return( primary_name );
  692.             }
  693.             while( *cp && *cp != '|' )
  694.                 cp++;
  695.             if( *cp )               /* skip | */
  696.                 cp++;
  697.         } while( *cp && *cp != '\\' );
  698.     }
  699.     fclose( fp );
  700.     return( NULL );
  701. }
  702.  
  703. /*
  704. ** pc_get_number - get the numeric printer capability corresponding 
  705. **           to id.  Returns the value, -1 if invalid.
  706. */
  707. static int
  708. pc_get_number( bp, id )
  709. char *bp, *id;
  710. {
  711.     char *cp;
  712.     int ret;
  713.  
  714.     if( (cp = bp) == NULL || id == NULL )
  715.         return( -1 );
  716.     while( *++cp != ':' )
  717.         ;
  718.     for( ++cp; *cp; ) {
  719.         while( isspace( *cp ) )
  720.             cp++;
  721.         if( strncmp( cp, id, 2) == 0 ) {
  722.             while( *cp && *cp != ':' && *cp != '#' )
  723.                 cp++;
  724.             if( *cp != '#' )
  725.                 return( -1 );
  726.             for( ret = 0, cp++; *cp && isdigit( *cp ); cp++ )
  727.                 ret = ret * 10 + *cp - '0';
  728.             return( ret );
  729.         }
  730.         while( *cp && *cp != ':' )
  731.             cp++;
  732.         if( *cp )
  733.             cp++;
  734.     }
  735.     return( -1 );
  736. }
  737.  
  738. /*
  739. ** pc_get_flag - get the boolean flag corresponding to id.  Returns
  740. **            -1 if invalid, FALSE if the flag is not in the printcap
  741. **            entry, or TRUE if it is present.
  742. */
  743. static int
  744. pc_get_flag( bp, id )
  745. char *bp, *id;
  746. {
  747.     char *cp;
  748.  
  749.     if( (cp = bp) == NULL || id == NULL )
  750.         return( -1 );
  751.     while( *++cp != ':' )
  752.         ;
  753.     for( ++cp; *cp; ) {
  754.         while( isspace( *cp ) )
  755.             cp++;
  756.         if( strncmp( cp, id, 2) == 0 )
  757.                 return( TRUE );
  758.         while( *cp && *cp != ':' )
  759.                 cp++;
  760.         if( *cp )
  761.             cp++;
  762.     }
  763.     return( FALSE );
  764. }
  765.  
  766. /*
  767. ** pc_get_string - get the string capability corresponding to id and place
  768. **           it in area (advancing area to same time).  Expand escape
  769. **           sequences etc.  Returns the string, of NULL if it can't
  770. **           do it.
  771. */
  772. static char *
  773. pc_get_string( bp, id, area )
  774. char *bp, *id, **area;
  775. {
  776.     char *cp, *ret;
  777.     int i;
  778.  
  779.     if( (cp = bp) == NULL || id == NULL )
  780.         return( NULL );
  781.     while( *++cp != ':' )
  782.             ;
  783.     for( ++cp; *cp; ) {
  784.         while( isspace( *cp ) )
  785.             cp++;
  786.         if( strncmp( cp, id, 2) == 0 ) {
  787.             while( *cp && *cp != ':' && *cp != '=' )
  788.                 cp++;
  789.             if( *cp != '=' )
  790.                 return( NULL );
  791.             for( ret = *area, cp++; *cp && *cp != ':'; (*area)++, cp++ )
  792.                 switch( *cp ) {
  793.                     case '^':
  794.                         **area = *++cp - 'A';
  795.                         break;
  796.                     case '\\':
  797.                         switch( *++cp ) {
  798.                             case 'E':
  799.                                 **area = '\033';
  800.                                 break;
  801.                             case 'n':
  802.                                 **area = '\n';
  803.                                 break;
  804.                             case 'r':
  805.                                 **area = '\r';
  806.                                 break;
  807.                             case 't':
  808.                                 **area = '\t';
  809.                                 break;
  810.                             case 'b':
  811.                                 **area = '\b';
  812.                                 break;
  813.                             case 'f':
  814.                                 **area = '\f';
  815.                                 break;
  816.                             case '0':
  817.                             case '1':
  818.                             case '2':
  819.                             case '3':
  820.                                 for( i = 0; *cp && isdigit( *cp ); cp++ )
  821.                                     i = i * 8 + *cp - '0';
  822.                                 **area = i & 0x7f;    /* strip high bit */
  823.                                 cp--;
  824.                                 break;
  825.                             case '^':
  826.                             case '\\':
  827.                                 **area = *cp;
  828.                                 break;
  829.                         }
  830.                         break;
  831.                     default:
  832.                         **area = *cp;
  833.                 }
  834.             *(*area)++ = '\0';
  835.             return( ret );
  836.         }
  837.         while( *cp && *cp != ':' )
  838.             cp++;
  839.         if( *cp )
  840.             cp++;
  841.     }
  842.     return( NULL );
  843. }
  844.  
  845. /*
  846.  * Get a count of the number of queues specified in the printcap
  847.  */
  848. static unsigned int
  849. get_queue_count()
  850. {
  851.     FILE *fp;
  852.     unsigned int queue_count = 0;
  853.     char *buffer;
  854.  
  855. #ifdef LPD_DEBUG
  856.     tprintf( "get_queue_count()\n" );
  857.     tflush();
  858. #endif
  859.  
  860.     if( (fp = fopen( Lpdprintcap, "r" )) == (FILE *) NULL )
  861.             return NULL;
  862.  
  863.     buffer = (char *)mallocw( 1024 );
  864.  
  865.     while( fgets( buffer, 1024, fp ) != NULL ) {
  866.         /* skip comments */
  867.         if( *buffer == '#' )
  868.                 continue;
  869.  
  870.         if( *buffer != '\n' ) {
  871.             queue_count++;
  872.             while( *(buffer + strlen( buffer ) - 2) == '\\' )
  873.                     fgets( buffer, 1024, fp );
  874.         }
  875.         YIELD;
  876.     }
  877.     fclose( fp );
  878.     free( buffer );
  879.     return( queue_count );
  880. }
  881.  
  882. /*
  883.  * Scans the printcap file and extracts the names of all queues.
  884.  */
  885. char **
  886. get_queue_list(void)
  887. {
  888.     FILE *fp;
  889.     char *cp, *strdup(), save;
  890.     char *buffer;
  891.     char **queue_list;
  892.     unsigned int queue_count = 0, queue_entry = 0;
  893.  
  894. #ifdef LPD_DEBUG
  895.     tprintf( "get_queue_list()\n" );
  896.     tflush();
  897. #endif
  898.  
  899.     queue_count = get_queue_count();
  900.     if( queue_count == 0 ) {
  901.         tprintf( "no queues defined in printcap file\n" );
  902.         return NULL;
  903.     }
  904.     queue_list = callocw( queue_count+1, sizeof( char * ) );
  905.  
  906.     buffer = mallocw( 1024 );
  907.  
  908.     fp = fopen( Lpdprintcap, "r" );
  909.  
  910.     while( fgets( buffer, 1024, fp ) != NULL ) {
  911.         /* skip comments */
  912.         if( *buffer == '#' )
  913.                 continue;
  914.         for( cp = buffer; isspace( *cp ) && *cp != '\n'; cp++ )
  915.                 ;
  916.         while( *cp && *cp != '|' && *cp != ':'
  917.                    && *cp != '\\' && *cp != '\n' )
  918.             cp++;
  919.         save = *cp;
  920.         *cp = NULL;
  921.  
  922.         if( *buffer )
  923.             queue_list[ queue_entry++ ] = strdup( buffer );
  924.         *cp = save;
  925.         while( *(buffer + strlen( buffer ) - 2) == '\\' )
  926.                 fgets( buffer, 1024, fp );
  927.         YIELD;
  928.     }
  929.     queue_list[ queue_entry ] = NULL;
  930.  
  931.     fclose( fp );
  932.     free( buffer );
  933.     return( queue_list );
  934. }
  935.  
  936. /*
  937.  * Get the SD (spool directory) associated with the specified queue
  938.  * from the printcap
  939.  */
  940. char *
  941. get_spool_dir( queue )
  942. char *queue;
  943. {
  944.     char *cp, *strdup();
  945.     char *bp, *sp, *osp;        /* buffer and string pointers */
  946.     char *primary_name;
  947.     char *sd;
  948.  
  949.     bp = (char *)mallocw( 1024 );
  950.  
  951.     /* look up corresponding printcap entry */
  952.  
  953.     if( (primary_name = pc_get_entry( bp, queue )) == NULL ) {
  954.         free( bp );
  955.         return NULL;
  956.     }
  957.     free( primary_name );
  958.     osp = sp = (char *)mallocw( 128 );
  959.  
  960.     if( (cp = pc_get_string( bp, "sd", &sp )) == NULL )
  961.         cp = Lpdsd;
  962.     if( *cp != '/' )
  963.         cp = rootdircat( cp );
  964.     sd = strdup( cp );
  965.  
  966.     free( osp );
  967.     free( bp );
  968.  
  969.     return sd;
  970. }
  971.  
  972. /*
  973.  * Get the AF (accounting file) and CO (page cost) associated
  974.  * with the specified queue from the printcap
  975.  */
  976. int
  977. get_acct_info( queue, af, pc )
  978. char *queue, **af;
  979. int *pc;
  980. {
  981.     char *cp, *strdup();
  982.     char *bp, *sp, *osp;        /* buffer and string pointers */
  983.     char *primary_name;
  984.  
  985.     bp = (char *)mallocw( 1024 );
  986.  
  987.     /* look up corresponding printcap entry */
  988.  
  989.     if( (primary_name = pc_get_entry( bp, queue )) == NULL ) {
  990.         free( bp );
  991.         return 1;
  992.     }
  993.     free( primary_name );
  994.     osp = sp = (char *)mallocw( 128 );
  995.  
  996.     if( (cp = pc_get_string( bp, "af", &sp )) == NULL ) {
  997.         *af = NULL;
  998.     } else {
  999.         *af = strdup( cp );
  1000.     }
  1001.     if( **af != '/' )
  1002.         *af = rootdircat( *af );
  1003.  
  1004.     if( (*pc = pc_get_number( bp, "co" )) < 0 )
  1005.         *pc = 0;
  1006.  
  1007.     free( osp );
  1008.     free( bp );
  1009.  
  1010.     return 0;
  1011. }
  1012.  
  1013. /*
  1014.  * Set up internal queue status structures. Read previous status from
  1015.  * disk or create a new status file.
  1016.  */
  1017. int
  1018. init_queue_status(void)
  1019. {
  1020.     char **pr, **opr, *strdup();    /* list of print queues */
  1021.     char *sd;
  1022.     unsigned int count;
  1023.     struct LPDstatus *ptr;
  1024.  
  1025. #ifdef LPD_DEBUG
  1026.     tprintf( "init_queue_status()\n" );
  1027.     tflush();
  1028. #endif
  1029.  
  1030.     count = get_queue_count();
  1031.     if( count == 0 ) {
  1032.         tprintf( "no queues defined in printcap file\n" );
  1033.         return -1;
  1034.     }
  1035.     queue_list = ptr = calloc( count+1, sizeof( struct LPDstatus ) );
  1036.  
  1037.     for( opr = pr = get_queue_list(); *pr; ++pr, ++ptr ){
  1038.         /* look up corresponding printcap entry */
  1039.  
  1040.         sd = get_spool_dir( *pr );
  1041.  
  1042.         read_lock_file( sd, &ptr->flags, &ptr->next_seq );
  1043.         free( sd );
  1044.  
  1045.         ptr->name = strdup( *pr );
  1046.         ptr->device_open = 0;
  1047.         ptr->type = EXTERNAL;        /* These will be set on the */
  1048.         ptr->device.fp = (FILE *)0;    /* call to open_device()    */
  1049.         ptr->jobno = 0;
  1050.         ptr->busy = 0;
  1051.         ptr->message = NULL;
  1052.  
  1053.         free( *pr );
  1054.     }
  1055.     free( *pr );    /* null entry */
  1056.     free( opr );
  1057.  
  1058.     /* last one is NULL */
  1059.     ptr->name = NULL;
  1060.  
  1061.     return 0;
  1062. }
  1063.  
  1064. /*
  1065.  * Free internal queue status structures.
  1066.  */
  1067. void
  1068. free_queue_status(void)
  1069. {
  1070.     struct LPDstatus *ptr;
  1071.  
  1072. #ifdef LPD_DEBUG
  1073.     tprintf( "free_queue_status()\n" );
  1074.     tflush();
  1075. #endif
  1076.  
  1077.     for( ptr = queue_list; ptr->name; ptr++ ) {
  1078.         free( ptr->name );
  1079.         if( ptr->message != NULL )
  1080.             free( ptr->message );
  1081.     }
  1082.     free( queue_list );
  1083. }
  1084.  
  1085. /*
  1086.  * Obtain new sequence number for a new job
  1087.  */
  1088. int
  1089. get_new_sequence_no( LPD )
  1090. struct LPDtrans *LPD;
  1091. {
  1092.     if( LPD->status == NULL ) {
  1093.         if( (LPD->status = get_status_entry( LPD->name )) == NULL )
  1094.             return -1;
  1095.     }
  1096.  
  1097.     LPD->status->next_seq++;
  1098.  
  1099.     write_lock_file( LPD->pc->SD, LPD->status->flags, LPD->status->next_seq );
  1100.  
  1101.     return( LPD->status->next_seq-1 );
  1102. }
  1103.  
  1104. /*
  1105.  * Read physical queue lock file contents.  If given file does not exist,
  1106.  * one is created with the default values.
  1107.  */
  1108. static void
  1109. read_lock_file( directory, flags, next_seq )
  1110. char *directory;
  1111. unsigned int *flags;
  1112. unsigned int *next_seq;
  1113. {
  1114.     char *path;
  1115.     int fd;
  1116.  
  1117.     path = pathname( directory, D_LOCK );
  1118.     if( (fd = open( path, O_RDONLY )) < 0 ) {
  1119.         fd = creat( path, 0644 );
  1120.         *flags = QUEUE_ENABLED | PRINT_ENABLED;
  1121.         *next_seq = 1;
  1122.         write( fd, flags, sizeof( *flags ) );
  1123.         write( fd, next_seq, sizeof( *next_seq ) );
  1124.         lseek( fd, 0L, 0 );
  1125.     }
  1126.     read( fd, flags, sizeof( *flags ) );
  1127.     read( fd, next_seq, sizeof( *next_seq ) );
  1128.     close( fd );
  1129.     free( path );
  1130.     YIELD;
  1131. }
  1132.  
  1133. /*
  1134.  * Write values to physical queue lock file.
  1135.  */
  1136. static void
  1137. write_lock_file( directory, flags, next_seq )
  1138. char *directory;
  1139. unsigned int flags;
  1140. unsigned int next_seq;
  1141. {
  1142.     char *path;
  1143.     int fd;
  1144.  
  1145.     path = pathname( directory, D_LOCK );
  1146.     fd = open( path, O_WRONLY|O_TRUNC|O_CREAT, 0644 );
  1147.     write( fd, &flags, sizeof( flags ) );
  1148.     write( fd, &next_seq, sizeof( next_seq ) );
  1149.     close( fd );
  1150.     free( path );
  1151.     YIELD;
  1152. }
  1153.  
  1154. /*
  1155.  * Load the status file for the given queue and extract its contents
  1156.  */
  1157. static int
  1158. load_status( queue, flags, next_seq )
  1159. char *queue;
  1160. unsigned int *flags;
  1161. unsigned int *next_seq;
  1162. {
  1163.     char *sd;
  1164.  
  1165.     if( (sd = get_spool_dir( queue )) == NULL )
  1166.         return -1;
  1167.  
  1168.     read_lock_file( sd, flags, next_seq );
  1169.     free( sd );
  1170.  
  1171.     return 0;
  1172. }
  1173.  
  1174. /*
  1175.  * Read the status of the specified queue from memory or disk as necessary
  1176.  */
  1177. int
  1178. read_status( queue, flags, next_seq, message )
  1179. char *queue;
  1180. unsigned int *flags;
  1181. unsigned int *next_seq;
  1182. char **message;
  1183. {
  1184.     char *primary_name;
  1185.     struct LPDstatus *status;
  1186.  
  1187. #ifdef LPD_DEBUG
  1188.     tprintf( "read_status( %s )\n", queue );
  1189.     tflush();
  1190. #endif
  1191.  
  1192.     if( is_lpd_active() ) {            /* Server is active */
  1193.  
  1194.         primary_name = get_primary_queue_name( queue );
  1195.         if( (status = get_status_entry( primary_name )) == NULL ) {
  1196.             free( primary_name );
  1197.             return -1;
  1198.         }
  1199.         free( primary_name );
  1200.  
  1201.         *flags = status->flags;
  1202.         *next_seq = status->next_seq;
  1203.         *message = status->message;
  1204.     } else {
  1205.         *message = "LPD server is not active";
  1206.         return( load_status( queue, flags, next_seq ) );
  1207.     }
  1208.  
  1209.     return 0;
  1210. }
  1211.  
  1212. /*
  1213.  * Set the flag bits specified in the queue status entry
  1214.  */
  1215. int
  1216. set_status_flag( queue, flag )
  1217. char *queue;
  1218. int flag;
  1219. {
  1220.     unsigned int flags, next_seq;
  1221.     char *message;
  1222.  
  1223.     if( read_status( queue, &flags, &next_seq, &message ) < 0 )
  1224.         return -1;
  1225.  
  1226.     flags |= flag;
  1227.  
  1228.     if( save_status( queue, flags, next_seq ) < 0 )
  1229.         return -1;
  1230.  
  1231.     return 0;
  1232. }
  1233.  
  1234. /*
  1235.  * Clear the flag bits specified in the queue status entry
  1236.  */
  1237. int
  1238. clear_status_flag( queue, flag )
  1239. char *queue;
  1240. int flag;
  1241. {
  1242.     unsigned int flags, next_seq;
  1243.     char *message;
  1244.  
  1245.     if( read_status( queue, &flags, &next_seq, &message ) < 0 )
  1246.         return -1;
  1247.  
  1248.     flags &= ~flag;
  1249.  
  1250.     if( save_status( queue, flags, next_seq ) < 0 )
  1251.         return -1;
  1252.  
  1253.     return 0;
  1254. }
  1255.  
  1256. int
  1257. save_status( queue, flags, next_seq )
  1258. char *queue;
  1259. unsigned int flags;
  1260. unsigned int next_seq;
  1261. {
  1262.     char *sd, *primary_name;
  1263.     struct LPDstatus *status;
  1264.  
  1265. #ifdef LPD_DEBUG
  1266.     tprintf( "save_status( %s )\n", queue );
  1267.     tflush();
  1268. #endif
  1269.  
  1270.     if( is_lpd_active() ) {            /* Server is active */
  1271.  
  1272.         primary_name = get_primary_queue_name( queue );
  1273.         if( (status = get_status_entry( primary_name )) == NULL ) {
  1274.             free( primary_name );
  1275.             return -1;
  1276.         }
  1277.         free( primary_name );
  1278.         status->flags = flags;
  1279.         status->next_seq = next_seq;
  1280.     }
  1281.  
  1282.     if( (sd = get_spool_dir( queue )) == NULL )
  1283.         return -1;
  1284.  
  1285.     write_lock_file( sd, flags, next_seq );
  1286.     free( sd );
  1287.  
  1288.     return 0;
  1289. }
  1290.  
  1291. /*
  1292.  * Signal a paused printer
  1293.  */
  1294. int
  1295. signal_queue( queue )
  1296. char *queue;
  1297. {
  1298.     unsigned int flags, next_seq;
  1299.     char *message, *primary_name;
  1300.     struct LPDstatus *status;
  1301.  
  1302.     if( read_status( queue, &flags, &next_seq, &message ) < 0 )
  1303.         return -1;
  1304.  
  1305.     flags &= ~PAUSED;
  1306.  
  1307.     if( save_status( queue, flags, next_seq ) < 0 )
  1308.         return -1;
  1309.  
  1310.     primary_name = get_primary_queue_name( queue );
  1311.     if( (status = get_status_entry( primary_name )) == NULL ) {
  1312.         free( primary_name );
  1313.         return -1;
  1314.     }
  1315.     free( primary_name );
  1316.  
  1317.     psignal( &status->flags, 1 );
  1318.  
  1319.     return 0;
  1320. }
  1321.  
  1322. /*
  1323.  * Kill the unspooler currently handling the given queue
  1324.  */
  1325. int
  1326. kill_unspooler( queue )
  1327. char *queue;
  1328. {
  1329.     char *primary_name;
  1330.     struct LPDstatus *status;
  1331.  
  1332.     primary_name = get_primary_queue_name( queue );
  1333.     if( (status = get_status_entry( primary_name )) == NULL ) {
  1334.         free( primary_name );
  1335.         return -1;
  1336.     }
  1337.     free( primary_name );
  1338.  
  1339.     if( status->unspooler_proc != NULLPROC ) {
  1340.         killproc( status->unspooler_proc );
  1341.         status->unspooler_proc = NULLPROC;
  1342.         return 1;
  1343.     }
  1344.     return 0;
  1345. }
  1346.  
  1347. /*
  1348.  * Return the status of an unspooler for the specified queue.
  1349.  * Also return the cf_name of the currently active job.
  1350.  */
  1351. int
  1352. is_unspooler_active( queue, job )
  1353. char *queue, **job;
  1354. {
  1355.     char *primary_name;
  1356.     struct LPDstatus *status;
  1357.  
  1358.     *job = NULL;
  1359.     if( is_lpd_active() ) {
  1360.         primary_name = get_primary_queue_name( queue );
  1361.         if( (status = get_status_entry( primary_name )) == NULL ) {
  1362.             free( primary_name );
  1363.             return 0;    /* nope */
  1364.         }
  1365.         free( primary_name );
  1366.  
  1367.         if( status->unspooler_proc == NULLPROC )
  1368.             return 0;    /* also not */
  1369.  
  1370.         *job = status->current_job;
  1371.         return 1;        /* otherwise, must be active */
  1372.     }
  1373.     return 0;    /* server cannot be active */
  1374. }
  1375.  
  1376. /*
  1377.  * Get the job count for the given queue
  1378.  */
  1379. int
  1380. get_job_count( queue )
  1381. char *queue;
  1382. {
  1383.     char *path, *sd;
  1384.     unsigned int job_count = 0;
  1385.     struct ffblk file_info;
  1386.  
  1387.     if( (sd = get_spool_dir( queue )) == NULL )
  1388.         return -1;
  1389.  
  1390.     path = pathname( sd, "cf*.*" );
  1391.     free( sd );
  1392.     if( findfirst( path, &file_info, 0 ) == 0 ) {
  1393.         job_count++;
  1394.         while( findnext( &file_info ) == 0 )
  1395.             job_count++;
  1396.     }
  1397.     free( path );
  1398.  
  1399.     YIELD;
  1400.     return( job_count );
  1401. }
  1402.  
  1403. /*
  1404.  * Return the primary queue name of the (possibly) given queue alias
  1405.  */
  1406. static char *
  1407. get_primary_queue_name( queue )
  1408. char *queue;
  1409. {
  1410.     char *bp, *primary_name;
  1411.  
  1412.     bp = (char *)mallocw( 1024 );
  1413.  
  1414.     /* look up corresponding printcap entry */
  1415.  
  1416.     if( (primary_name = pc_get_entry( bp, queue )) == NULL ) {
  1417.         free( bp );
  1418.         return NULL;
  1419.     }
  1420.     free( bp );
  1421.  
  1422.     return( primary_name );
  1423. }
  1424.  
  1425. /*
  1426.  * locate device entry for the specified printer device
  1427.  */
  1428. struct LPDdevice *
  1429. get_device_entry( device_name )
  1430. char *device_name;
  1431. {
  1432.     struct LPDdevice *dptr;
  1433.  
  1434.     dptr = device_list;
  1435.     while( dptr->name != NULL ) {
  1436.         if( strcmp( dptr->name, device_name ) == 0 )
  1437.             return( dptr );
  1438.         dptr++;
  1439.     }
  1440.     return( NULL );                /* not found */
  1441. }
  1442.  
  1443. /*
  1444.  * locate status entry for the specified queue
  1445.  */
  1446. struct LPDstatus *
  1447. get_status_entry( queue )
  1448. char *queue;
  1449. {
  1450.     struct LPDstatus *sptr;
  1451.  
  1452.     sptr = queue_list;
  1453.     while( sptr->name != NULL ) {
  1454.         if( strcmp( sptr->name, queue ) == 0 )
  1455.             return( sptr );
  1456.         sptr++;
  1457.     }
  1458.     return( NULL );                /* not found */
  1459. }
  1460.  
  1461. /*
  1462.  * Internal status message routine
  1463.  */
  1464. static void
  1465. i_set_status_message( char **dest, char *message, va_list args )
  1466. {
  1467.     char buffer[128];
  1468.  
  1469.     vsprintf( buffer, message, args );
  1470.     rip( buffer );
  1471.     if( *dest != NULL )
  1472.         free( *dest );
  1473.     *dest = strdup( buffer );
  1474. }
  1475.  
  1476. /*
  1477.  * Set the status message as specified
  1478.  */
  1479. void
  1480. set_status_message( char **dest, char *message, ... )
  1481. {
  1482.     va_list args;
  1483.  
  1484.     va_start( args, message );
  1485.     i_set_status_message( dest, message, args );
  1486.     va_end( args );
  1487. }
  1488.  
  1489. /*
  1490.  * Return a pointer to a static data area containing the formatted date
  1491.  * and time.
  1492.  */
  1493. char *
  1494. time_string(void)
  1495. {
  1496.     time_t current_time;
  1497.  
  1498.     time( ¤t_time );
  1499.     return( ctime( ¤t_time ) );
  1500. }
  1501.  
  1502. /*
  1503.  * Internal log routine
  1504.  */
  1505. static void
  1506. i_lpd_log( struct LPDtrans *LPD, char *message, va_list args )
  1507. {
  1508.     char buffer[128], timeb[30];
  1509.  
  1510.     vsprintf( buffer, message, args );
  1511.     strcpy( timeb, time_string() );
  1512.     rip( timeb );
  1513.     fputs( timeb, LPD->logfp );
  1514.     fputs( " - ", LPD->logfp );
  1515.     fputs( buffer, LPD->logfp );
  1516.     putc( '\n', LPD->logfp );
  1517. }
  1518.  
  1519. /*
  1520.  * Log a message to the logfile
  1521.  */
  1522. void
  1523. lpd_log( struct LPDtrans *LPD, char *message, ... )
  1524. {
  1525.     va_list args;
  1526.  
  1527.     if( LPD->logfp == NULL )        /* no logging */
  1528.         return;
  1529.  
  1530.     va_start( args, message );
  1531.     i_lpd_log( LPD, message, args );
  1532.     va_end( args );
  1533. }
  1534.